﻿using System;
using System.ComponentModel;
using System.Data.Linq;
using System.Data.Linq.Mapping;

namespace GrimorioApplication.Model
{
    /*
     *  int RecipeId
     *  string RecipeName
     *  string Dish
     *  Boolean IsVegetarian
     *  string Difficulty
     *  double Stars   -> toolkit has rating! :D
     *  string TimeForPreparation
     *  string Description
     *  string NumberOfPeople
     *  string Matchings
     *  byte[] Image
     *  
     *  EntitySet<RecipeIngredients> IngredientsQuantity
     */

    [Table]
    public class DataRecipe : INotifyPropertyChanged, INotifyPropertyChanging
    {
        [Column(IsVersion = true)]
        private Binary _version;

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region INotifyPropertyChanging Members
        public event PropertyChangingEventHandler PropertyChanging;

        private void NotifyPropertyChanging(string propertyName)
        {
            if (PropertyChanging != null)
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }
        #endregion

        private int _recipeId;
        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
        public int RecipeId
        {
            get { return _recipeId; }
            set
            {
                if (_recipeId != value)
                {
                    NotifyPropertyChanging("RecipeId");
                    _recipeId = value;
                    NotifyPropertyChanged("RecipeId");
                }
            }
        }

        private string _recipeName;
        [Column]
        public string RecipeName
        {
            get { return _recipeName; }
            set
            {
                if (_recipeName != value)
                {
                    NotifyPropertyChanging("RecipeName");
                    _recipeName = value;
                    NotifyPropertyChanged("RecipeName");
                }
            }
        }

        private string _dish;
        [Column(CanBeNull = true)]
        public string Dish
        {
            get { return _dish; }
            set
            {
                if (_dish != value)
                {
                    NotifyPropertyChanging("Dish");
                    _dish = value;
                    NotifyPropertyChanged("Dish");
                }
            }
        }

        private Boolean _isVegetarian;
        [Column(CanBeNull = false)]
        public Boolean IsVegetarian
        {
            get { return _isVegetarian; }
            set
            {
                if (_isVegetarian != value)
                {
                    NotifyPropertyChanging("IsVegetarian");
                    _isVegetarian = value;
                    NotifyPropertyChanged("IsVegetarian");
                }
            }
        }

        private string _difficulty;
        [Column()]
        public string Difficulty
        {
            get { return _difficulty; }
            set
            {
                if (_difficulty != value)
                {
                    NotifyPropertyChanging("Difficulty");
                    _difficulty = value;
                    NotifyPropertyChanged("Difficulty");
                }
            }
        }

        private double _rating;
        [Column()]
        public double Rating
        {
            get { return _rating; }
            set
            {
                if (_rating != value)
                {
                    NotifyPropertyChanging("Rating");
                    _rating = value;
                    NotifyPropertyChanged("Rating");
                }
            }
        }

        private string _timeForPreparation;
        [Column()]
        public string TimeForPreparation
        {
            get { return _timeForPreparation; }
            set
            {
                if (_timeForPreparation != value)
                {
                    NotifyPropertyChanging("TimeForPreparation");
                    _timeForPreparation = value;
                    NotifyPropertyChanged("TimeForPreparation");
                }
            }
        }

        private string _preparation;
        [Column()]
        public string Preparation
        {
            get { return _preparation; }
            set
            {
                if (_preparation != value)
                {
                    NotifyPropertyChanging("Preparation");
                    _preparation = value;
                    NotifyPropertyChanged("Preparation");
                }
            }
        }

        private string _description;
        [Column()]
        public string Description
        {
            get { return _description; }
            set
            {
                if (_description != value)
                {
                    NotifyPropertyChanging("Description");
                    _description = value;
                    NotifyPropertyChanged("Description");
                }
            }
        }

        private int _numberOfPeople;
        [Column()]
        public int NumberOfPeople
        {
            get { return _numberOfPeople; }
            set
            {
                if (_numberOfPeople != value)
                {
                    NotifyPropertyChanging("NumberOfPeople");
                    _numberOfPeople = value;
                    NotifyPropertyChanged("NumberOfPeople");
                }
            }
        }

        private string _matchings;
        [Column()]
        public string Matchings
        {
            get { return _matchings; }
            set
            {
                if (_matchings != value)
                {
                    NotifyPropertyChanging("Matchings");
                    _matchings = value;
                    NotifyPropertyChanged("Matchings");
                }
            }
        }

        private string _image;
        [Column]
        public string Image
        {
            get { return _image; }
            set
            {
                NotifyPropertyChanging("Image");
                _image = value;
                NotifyPropertyChanged("Image");
            }
        }

        // ASSOCIATION
        //recipe to recipeIngredients (one to many, one side)

        private EntitySet<RecipeIngredients> _ingredientsQuantity; // = new EntitySet<RecipeIngredients>();
        [Association(Name = "RecipeToRecipeIngredients", Storage = "_ingredientsQuantity", OtherKey = "_recipeID", ThisKey = "RecipeId")]
        public EntitySet<RecipeIngredients> IngredientsQuantity
        {
            get { return _ingredientsQuantity; }
            set { _ingredientsQuantity = value; }
        }

        public DataRecipe()
        {
            _ingredientsQuantity = new EntitySet<RecipeIngredients>(
                new Action<RecipeIngredients>(this.attach_ingQuantity),
                new Action<RecipeIngredients>(this.detach_ingQuantity)
                );
        }

        // Called during an add operation
        private void attach_ingQuantity(RecipeIngredients quantityIngredient)
        {
            NotifyPropertyChanging("RecipeIngredients");
            quantityIngredient.Recipe = this;
        }

        private void detach_ingQuantity(RecipeIngredients quantityIngredient)
        {
            NotifyPropertyChanging("RecipeIngredients");
            quantityIngredient.Recipe = null;
        }
    }


    /*
     *  int RecipeIngredientsID
     *  string Quantity
     *  
     *  DataRecipe Recipe
     *  Ingredients Ingredient
     */

    [Table]
    public class RecipeIngredients
    {
        [Column(IsVersion = true)]
        private Binary _version;

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region INotifyPropertyChanging Members
        public event PropertyChangingEventHandler PropertyChanging;

        private void NotifyPropertyChanging(string propertyName)
        {
            if (PropertyChanging != null)
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }
        #endregion


        private int _recipeIngredientsID;
        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
        public int RecipeIngredientsID
        {
            get { return _recipeIngredientsID; }
            set
            {
                if (_recipeIngredientsID != value)
                {
                    NotifyPropertyChanging("RecipeIngredientsID");
                    _recipeIngredientsID = value;
                    NotifyPropertyChanged("RecipeIngredientsID");
                }
            }
        }

        private string _quantity;
        [Column]
        public string Quantity
        {
            get { return _quantity; }
            set
            {
                if (_quantity != value)
                {
                    NotifyPropertyChanging("Quantity");
                    _quantity = value;
                    NotifyPropertyChanged("Quantity");
                }
            }
        }

        // ASSOCIATIONS

        //recipe to recipeIngredients (one to many, many side)

        [Column()]
        internal int _recipeID;

        private EntityRef<DataRecipe> _recipe;
        [Association(Name = "RecipeToRecipeIngredients", Storage = "_recipe", ThisKey = "_recipeID", OtherKey = "RecipeId", IsForeignKey = true)]
        public DataRecipe Recipe
        {
            get { return _recipe.Entity; }
            set
            {
                DataRecipe previous = this._recipe.Entity;
                if (previous != value || this._recipe.HasLoadedOrAssignedValue == false)
                {
                    if (previous != null)
                    {
                        this._recipe.Entity = null;
                        previous.IngredientsQuantity.Remove(this);
                    }

                    this._recipe.Entity = value;

                    if (value != null)
                    {
                        value.IngredientsQuantity.Add(this);
                        // NOtificare il cambiamento
                        NotifyPropertyChanged("Recipe");
                    }
                }
            }
        }

        // recipeIngredients to ingredient (one to many, many side)

        [Column()]
        internal int? _ingredientID;

        private EntityRef<Ingredients> _ingredient;
        [Association(Name = "IngredientToRecipeIngredients", Storage = "_ingredient", ThisKey = "_ingredientID", OtherKey = "IngredientsID", IsForeignKey = true)]
        public Ingredients Ingredient
        {
            get { return _ingredient.Entity; }
            set
            {
                Ingredients previous = this._ingredient.Entity;
                if (previous != value || this._ingredient.HasLoadedOrAssignedValue == false)
                {
                    if (previous != null)
                    {
                        this._ingredient.Entity = null;
                        previous.RecipeQuantity.Remove(this);
                    }

                    this._ingredient.Entity = value;

                    if (value != null)
                    {
                        value.RecipeQuantity.Add(this);
                        // NOtificare il cambiamento
                        NotifyPropertyChanged("Ingredient");
                    }
                }
            }
        }
    }


    /*
     *  int IngredientsID
     *  string IngredientName
     *  
     *  EntitySet<RecipeIngredients> IngredientsQuantity
     */

    [Table]
    public class Ingredients
    {
        [Column(IsVersion = true)]
        private Binary _version;

        #region INotifyPropertyChanged Members
        public event PropertyChangedEventHandler PropertyChanged;

        private void NotifyPropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion

        #region INotifyPropertyChanging Members
        public event PropertyChangingEventHandler PropertyChanging;

        private void NotifyPropertyChanging(string propertyName)
        {
            if (PropertyChanging != null)
            {
                PropertyChanging(this, new PropertyChangingEventArgs(propertyName));
            }
        }
        #endregion

        private int _ingredientsID;
        [Column(IsPrimaryKey = true, IsDbGenerated = true, DbType = "INT NOT NULL Identity", CanBeNull = false, AutoSync = AutoSync.OnInsert)]
        public int IngredientsID
        {
            get { return _ingredientsID; }
            set
            {
                if (_ingredientsID != value)
                {
                    NotifyPropertyChanging("IngredientsID");
                    _ingredientsID = value;
                    NotifyPropertyChanged("IngredientsID");
                }
            }
        }

        private string _ingredientName;
        [Column]
        public string IngredientName
        {
            get { return _ingredientName; }
            set
            {
                if (_ingredientName != value)
                {
                    NotifyPropertyChanging("IngredientName");
                    _ingredientName = value;
                    NotifyPropertyChanged("IngredientName");
                }
            }
        }


        // ASSOCIATIONS

        // recipeIngredients to ingredients (one to many, one side)

        private EntitySet<RecipeIngredients> _recipeQuantity; // = new EntitySet<RecipeIngredients>();
        [Association(Name = "IngredientToRecipeIngredients", Storage = "_recipeQuantity", OtherKey = "_ingredientID", ThisKey = "IngredientsID")]
        public EntitySet<RecipeIngredients> RecipeQuantity
        {
            get { return _recipeQuantity; }
            set { _recipeQuantity = value; }
        }


        public Ingredients()
        {
            _recipeQuantity = new EntitySet<RecipeIngredients>(
                new Action<RecipeIngredients>(this.attach_recQuantity),
                new Action<RecipeIngredients>(this.detach_recQuantity)
                );
        }

        // Called during an add operation
        private void attach_recQuantity(RecipeIngredients quantityRecipe)
        {
            NotifyPropertyChanging("RecipeIngredients");
            quantityRecipe.Ingredient = this;
        }

        private void detach_recQuantity(RecipeIngredients quantityRecipe)
        {
            NotifyPropertyChanging("RecipeIngredients");
            quantityRecipe.Ingredient = null;
        }
    }


    public class GrimorioDataContext : DataContext
    {
        public GrimorioDataContext(string connectionString) : base(connectionString) { }

        public Table<DataRecipe> RecipesT;

        public Table<RecipeIngredients> RecipeToIngT;

        public Table<Ingredients> IngredientsT;

    }
}